package user

import (
	"context"
	"git.mycaigou.com/gfyx/common/tenant_db"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/common/constants"
	"github.com/google/uuid"
	"gorm.io/gorm"
	"time"
)

type userOrgRepository struct {
	tenant_db.TenantDB
}

// NewUserOrgRepository 构造函数
func NewUserOrgRepository() UserOrgRepositoryIface {
	return &userOrgRepository{}
}

// GetUsersByOrgId 根据部门编号获取部门员工
func (r *userOrgRepository) GetUsersByOrgId(ctx context.Context, orgId int64) ([]*GfyxUserOrganizationRelationPo, error) {
	list := make([]*GfyxUserOrganizationRelationPo, 0)
	err := r.GetTenantDB(ctx).
		Where("organization_id = ? and is_deleted = ?", orgId, constants.IsDeletedFalse).Find(&list).Error
	if err != nil {
		return list, err
	}

	if err != nil && err != gorm.ErrRecordNotFound {
		return nil, err
	}

	return list, nil
}

// GetAllUsersByOrgId 根据部门编号获取所有子部门的员工
func (r *userOrgRepository) GetAllUsersByOrgId(ctx context.Context, orgIds []int64) ([]*GfyxUserOrganizationRelationPo, error) {
	list := make([]*GfyxUserOrganizationRelationPo, 0)
	err := r.GetTenantDB(ctx).
		Where("organization_id in (?) and is_deleted = ?", orgIds, constants.IsDeletedFalse).
		Find(&list).Error
	return list, err
}

// GetListByUserIds 根据用户编号获取部门信息
func (r *userOrgRepository) GetListByUserIds(ctx context.Context, userIds []int64) ([]*GfyxUserOrganizationRelationPo, error) {
	list := make([]*GfyxUserOrganizationRelationPo, 0)
	err := r.GetTenantDB(ctx).
		Where("user_id in (?) and is_deleted = ?", userIds, constants.IsDeletedFalse).
		Find(&list).Error
	return list, err
}

// SetDepartmentHeader 设置负责人/取消负责人
func (r *userOrgRepository) SetDepartmentHeader(ctx context.Context, userIds []int64, orgId int64, userGuids []string, orgGuid string) error {
	db := r.GetTenantDB(ctx).Begin()
	userOrgObjList := make([]*GfyxUserResponsibleOrganizationRelationPo, 0)
	err := db.
		Where("organization_id = ? and is_deleted = ?", orgId, constants.IsDeletedFalse).
		Find(&userOrgObjList).Error
	if err != nil && err != gorm.ErrRecordNotFound {
		db.Rollback()
		return err
	}

	/*
		userIds 有	userOrgObjList 没有   -> 新增
		userIds 没有 userOrgObjList 有    -> 删除
		userIds 有 userOrgObjList   有    -> 无变化
	*/
	addUserIds, delUserIds := make([]int64, 0), make([]int64, 0)
	for _, userId := range userIds {
		isMatch := false
		for _, item := range userOrgObjList {
			if userId == item.UserId {
				isMatch = true
				break
			}
		}
		if !isMatch {
			addUserIds = append(addUserIds, userId)
		}
	}
	for _, item := range userOrgObjList {
		isMatch := false
		for _, userId := range userIds {
			if userId == item.UserId {
				isMatch = true
				break
			}
		}
		if !isMatch {
			delUserIds = append(delUserIds, item.UserId)
		}
	}

	if len(delUserIds) > 0 {
		err := db.
			Table(GfyxUserResponsibleOrganizationRelationPo{}.TableName()).
			Where("user_id in (?) and organization_id = ? and is_deleted = ?", delUserIds, orgId, constants.IsDeletedFalse).
			Updates(map[string]interface{}{
				"is_deleted":  1,
				"modified_on": time.Now(),
			}).Error
		if err != nil {
			db.Rollback()
			return err
		}
	}

	if len(addUserIds) > 0 {
		for _, userId := range addUserIds {
			inUserOrgObj := &GfyxUserResponsibleOrganizationRelationPo{
				UserId:         userId,
				OrganizationId: orgId,
				CreatedOn:      time.Now(),
				CreatedBy:      "",
				ModifiedOn:     time.Now(),
				ModifiedBy:     "",
			}
			if err := db.Save(inUserOrgObj).Error; err != nil {
				db.Rollback()
				return err
			}
		}
	}

	// 建模表——设置负责人
	gfyxPermuser := GfyxPermuser{}
	if err := db.Where("ManagedBUGUID = ?", orgGuid).Delete(&gfyxPermuser).Error; err != nil {
		db.Rollback()
		return err
	}
	for _, userGuid := range userGuids {
		err = db.Create(&GfyxPermuser{
			PermUserGUID:  uuid.New().String(),
			ManagedBUGUID: orgGuid,
			PermTypeGUID:  "60cd6004-4ac7-11ed-a7bf-0242ac120006",
			UserGUID:      userGuid,
			CreatedName:   "双写同步",
			CreatedTime:   time.Now(),
			ModifiedName:  "双写同步",
			ModifiedTime:  time.Now(),
			VersionNumber: time.Now(),
		}).Error
		if err != nil {
			db.Rollback()
			return err
		}
	}

	db.Commit()
	return nil
}

func (r *userOrgRepository) AppendDepartmentHeader(ctx context.Context, userId int64, orgId int64, userGuid string, orgGuid string) error {
	db := r.GetTenantDB(ctx).Begin()
	inUserOrgObj := &GfyxUserResponsibleOrganizationRelationPo{
		UserId:         userId,
		OrganizationId: orgId,
		CreatedOn:      time.Now(),
		CreatedBy:      "",
		ModifiedOn:     time.Now(),
		ModifiedBy:     "",
	}
	if err := db.Create(inUserOrgObj).Error; err != nil {
		db.Rollback()
		return err
	}

	err := db.Create(&GfyxPermuser{
		PermUserGUID:  uuid.New().String(),
		ManagedBUGUID: orgGuid,
		PermTypeGUID:  "60cd6004-4ac7-11ed-a7bf-0242ac120006",
		UserGUID:      userGuid,
		CreatedName:   "双写同步",
		CreatedTime:   time.Now(),
		ModifiedName:  "双写同步",
		ModifiedTime:  time.Now(),
		VersionNumber: time.Now(),
	}).Error
	if err != nil {
		db.Rollback()
		return err
	}
	db.Commit()
	return nil
}

// SetDepartmentHeaderNew 临时处理
func (r *userOrgRepository) SetDepartmentHeaderNew(ctx context.Context, userIds []int64, orgId int64) error {
	// todo 临时处理
	db := r.GetTenantDB(ctx)
	userOrgObjList := make([]*GfyxUserResponsibleOrganizationRelationPo, 0)
	err := db.
		Where("organization_id = ? and is_deleted = ?", orgId, constants.IsDeletedFalse).
		Find(&userOrgObjList).Error
	if err != nil && err != gorm.ErrRecordNotFound {
		return err
	}
	addUserIds, delUserIds := make([]int64, 0), make([]int64, 0)
	for _, userId := range userIds {
		isMatch := false
		for _, item := range userOrgObjList {
			if userId == item.UserId {
				isMatch = true
				break
			}
		}
		if !isMatch {
			addUserIds = append(addUserIds, userId)
		}
	}
	for _, item := range userOrgObjList {
		isMatch := false
		for _, userId := range userIds {
			if userId == item.UserId {
				isMatch = true
				break
			}
		}
		if !isMatch {
			delUserIds = append(delUserIds, item.UserId)
		}
	}

	if len(delUserIds) > 0 {
		err := db.
			Table(GfyxUserResponsibleOrganizationRelationPo{}.TableName()).
			Where("user_id in (?) and organization_id = ? and is_deleted = ?", delUserIds, orgId, constants.IsDeletedFalse).
			Updates(map[string]interface{}{
				"is_deleted":  1,
				"modified_on": time.Now(),
			}).Error
		if err != nil {
			return err
		}
	}

	if len(addUserIds) > 0 {
		for _, userId := range addUserIds {
			inUserOrgObj := &GfyxUserResponsibleOrganizationRelationPo{
				UserId:         userId,
				OrganizationId: orgId,
				CreatedOn:      time.Now(),
				CreatedBy:      "",
				ModifiedOn:     time.Now(),
				ModifiedBy:     "",
			}
			if err := db.Save(inUserOrgObj).Error; err != nil {
				return err
			}
		}
	}
	return nil
}

// GetUserResponsibleList 获取区域负责人
func (r *userOrgRepository) GetUserResponsibleList(ctx context.Context) ([]*UserResponsible, error) {
	userResponsible := make([]*UserResponsible, 0)
	err := r.GetTenantDB(ctx).
		Select("A.organization_id, A.user_id, B.name").
		Table(GfyxUserResponsibleOrganizationRelationPo{}.TableName()+" A").
		Joins("inner join "+GfyxUserPo{}.TableName()+" B on A.user_id = B.id").
		Where("A.is_deleted = ? and B.is_deleted = ?", 0, 0).Find(&userResponsible).Error
	if err != nil && err != gorm.ErrRecordNotFound {
		return nil, err
	}
	return userResponsible, nil
}

// GetMyResponseOrgUserIds 获取我负责的区域的所有用户id
// 1，先算出我负责的区域
// 2，通过区域 id 查出这些区域的用户信息
func (r *userOrgRepository) GetMyResponseOrgUserIds(ctx context.Context, userId int64) ([]int64, error) {
	var userIds []int64
	err := r.GetTenantDB(ctx).
		Select("ue.user_id AS user_id").
		Table("gfyx_user_responsible_organization re").
		Joins("INNER JOIN gfyx_organization o ON o.id = re.organization_id").
		Joins("LEFT JOIN gfyx_user_organization_relation ue ON ue.organization_id = o.id").
		Where("re.user_id = ? and re.is_deleted = ? and o.is_deleted = ? and ue.is_deleted = ?", userId, constants.IsDeletedFalse, constants.IsDeletedFalse, constants.IsDeletedFalse).
		Pluck("user_id", &userIds).Error
	if err != nil && err != gorm.ErrRecordNotFound {
		return nil, err
	}
	return userIds, nil
}

// GetMyResponseSubOrgUserIds 获取我负责的区域的子区域的所有用户id
// 1，先算出我负责的区域
// 2, 再通过区域名称再去模糊查询区域（因为名称的命名关系 full name 的名称是按照层级拼接的）
// 3，通过区域 id 查出这些区域的用户信息
func (r *userOrgRepository) GetMyResponseSubOrgUserIds(ctx context.Context, userId int64) ([]int64, error) {
	var userIds []int64
	err := r.GetTenantDB(ctx).
		Select("ue.user_id AS user_id").
		Table("gfyx_user_responsible_organization re").
		Joins("INNER JOIN gfyx_organization o ON o.id = re.organization_id").
		Joins("LEFT JOIN gfyx_organization os ON ( os.full_name LIKE concat( o.full_name, '-%' ) )").
		Joins("LEFT JOIN gfyx_user_organization_relation ue ON ue.organization_id = os.id").
		Where("re.user_id = ? and re.is_deleted = ? and o.is_deleted = ? and os.is_deleted = ? and ue.is_deleted = ?", userId, constants.IsDeletedFalse, constants.IsDeletedFalse, constants.IsDeletedFalse, constants.IsDeletedFalse).
		Pluck("user_id", &userIds).Error
	if err != nil && err != gorm.ErrRecordNotFound {
		return nil, err
	}
	return userIds, nil
}

func (r *userOrgRepository) GetMyResponseOrgUserGuids(ctx context.Context, userId int64) ([]string, error) {
	var userIds []string
	err := r.GetTenantDB(ctx).
		Select("u.uid AS user_id").
		Table("gfyx_user_responsible_organization re").
		Joins("INNER JOIN gfyx_organization o ON o.id = re.organization_id").
		Joins("LEFT JOIN gfyx_user_organization_relation ue ON ue.organization_id = o.id").
		Joins("LEFT JOIN gfyx_user u ON u.id = ue.user_id").
		Where("re.user_id = ? and re.is_deleted = ? and o.is_deleted = ? and ue.is_deleted = ? and u.is_deleted = ? ", userId, constants.IsDeletedFalse, constants.IsDeletedFalse, constants.IsDeletedFalse, constants.IsDeletedFalse).
		Pluck("user_id", &userIds).Error
	if err != nil && err != gorm.ErrRecordNotFound {
		return nil, err
	}
	return userIds, nil
}

func (r *userOrgRepository) GetMyResponseSubOrgUserGuids(ctx context.Context, userId int64) ([]string, error) {
	var userIds []string
	err := r.GetTenantDB(ctx).
		Select("u.uid AS user_id").
		Table("gfyx_user_responsible_organization re").
		Joins("INNER JOIN gfyx_organization o ON o.id = re.organization_id").
		Joins("LEFT JOIN gfyx_organization os ON ( os.full_name LIKE concat( o.full_name, '-%' ) )").
		Joins("LEFT JOIN gfyx_user_organization_relation ue ON ue.organization_id = os.id").
		Joins("LEFT JOIN gfyx_user u ON u.id = ue.user_id").
		Where("re.user_id = ? and re.is_deleted = ? and o.is_deleted = ? and os.is_deleted = ? and ue.is_deleted = ? and u.is_deleted = ?", userId, constants.IsDeletedFalse, constants.IsDeletedFalse, constants.IsDeletedFalse, constants.IsDeletedFalse, constants.IsDeletedFalse).
		Pluck("user_id", &userIds).Error
	if err != nil && err != gorm.ErrRecordNotFound {
		return nil, err
	}
	return userIds, nil
}

func (r *userOrgRepository) DeletedUserOrgRelation(ctx context.Context, userId int64) error {
	err := r.GetTenantDB(ctx).Table(GfyxUserOrganizationRelationPo{}.TableName()).Where("user_id = ?", userId).Updates(map[string]interface{}{
		"is_deleted":  constants.IsDeletedTrue,
		"modified_on": time.Now(),
		"modified_by": "",
	}).Error
	if err != nil {
		return err
	}
	return nil
}

// SaveUserOrgRelation 保存用户组织关系
func (r *userOrgRepository) SaveUserOrgRelation(ctx context.Context, po *GfyxUserOrganizationRelationPo) error {
	return r.GetTenantDB(ctx).Save(po).Error
}
